home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / share / hplip / base / status.py < prev    next >
Text File  |  2009-10-09  |  55KB  |  1,454 lines

  1. # -*- coding: utf-8 -*-
  2. #
  3. # (c) Copyright 2003-2007 Hewlett-Packard Development Company, L.P.
  4. #
  5. # This program is free software; you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation; either version 2 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program; if not, write to the Free Software
  17. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  18. #
  19. # Author: Don Welch
  20. #
  21.  
  22. from __future__ import division
  23.  
  24. # Std Lib
  25. import struct
  26. import cStringIO
  27. import xml.parsers.expat as expat
  28. import re
  29.  
  30. # Local
  31. from g import *
  32. from codes import *
  33. import pml, utils
  34.  
  35.  
  36. """
  37. status dict structure:
  38.     { 'revision' :     STATUS_REV_00 .. STATUS_REV_04,
  39.       'agents' :       [ list of pens/agents/supplies (dicts) ],
  40.       'top-door' :     TOP_DOOR_NOT_PRESENT | TOP_DOOR_CLOSED | TOP_DOOR_OPEN,
  41.       'status-code' :  STATUS_...,
  42.       'supply-door' :  SUPPLY_DOOR_NOT_PRESENT | SUPPLY_DOOR_CLOSED | SUPPLY_DOOR_OPEN.
  43.       'duplexer' :     DUPLEXER_NOT_PRESENT | DUPLEXER_DOOR_CLOSED | DUPLEXER_DOOR_OPEN,
  44.       'photo_tray' :   PHOTO_TRAY_NOT_PRESENT | PHOTO_TRAY_ENGAGED | PHOTO_TRAY_NOT_ENGAGED,
  45.       'in-tray1' :     IN_TRAY_NOT_PRESENT | IN_TRAY_CLOSED | IN_TRAY_OPEN (| IN_TRAY_DEFAULT | IN_TRAY_LOCKED)*,
  46.       'in-tray2' :     IN_TRAY_NOT_PRESENT | IN_TRAY_CLOSED | IN_TRAY_OPEN (| IN_TRAY_DEFAULT | IN_TRAY_LOCKED)*,
  47.       'media-path' :   MEDIA_PATH_NOT_PRESENT | MEDIA_PATH_CUT_SHEET | MEDIA_PATH_BANNER | MEDIA_PATH_PHOTO,
  48.     }
  49.  
  50.     * S:02 only
  51.  
  52. agent dict structure: (pens/supplies/agents/etc)
  53.     { 'kind' :           AGENT_KIND_NONE ... AGENT_KIND_ADF_KIT,
  54.       'type' :           TYPE_BLACK ... AGENT_TYPE_UNSPECIFIED,      # aka color
  55.       'health' :         AGENT_HEALTH_OK ... AGENT_HEALTH_UNKNOWN,
  56.       'level' :          0 ... 100,
  57.       'level-trigger' :  AGENT_LEVEL_TRIGGER_SUFFICIENT_0 ... AGENT_LEVEL_TRIGGER_ALMOST_DEFINITELY_OUT,
  58.     }
  59. """
  60.  
  61.  
  62.  
  63. # 'revision'
  64. STATUS_REV_00 = 0x00
  65. STATUS_REV_01 = 0x01
  66. STATUS_REV_02 = 0x02
  67. STATUS_REV_03 = 0x03
  68. STATUS_REV_04 = 0x04
  69. STATUS_REV_V  = 0xff
  70. STATUS_REV_UNKNOWN = 0xfe
  71.  
  72. vstatus_xlate  = {'busy' : STATUS_PRINTER_BUSY,
  73.                    'idle' : STATUS_PRINTER_IDLE,
  74.                    'prnt' : STATUS_PRINTER_PRINTING,
  75.                    'offf' : STATUS_PRINTER_TURNING_OFF,
  76.                    'rprt' : STATUS_PRINTER_REPORT_PRINTING,
  77.                    'cncl' : STATUS_PRINTER_CANCELING,
  78.                    'iost' : STATUS_PRINTER_IO_STALL,
  79.                    'dryw' : STATUS_PRINTER_DRY_WAIT_TIME,
  80.                    'penc' : STATUS_PRINTER_PEN_CHANGE,
  81.                    'oopa' : STATUS_PRINTER_OUT_OF_PAPER,
  82.                    'bnej' : STATUS_PRINTER_BANNER_EJECT,
  83.                    'bnmz' : STATUS_PRINTER_BANNER_MISMATCH,
  84.                    'phmz' : STATUS_PRINTER_PHOTO_MISMATCH,
  85.                    'dpmz' : STATUS_PRINTER_DUPLEX_MISMATCH,
  86.                    'pajm' : STATUS_PRINTER_MEDIA_JAM,
  87.                    'cars' : STATUS_PRINTER_CARRIAGE_STALL,
  88.                    'paps' : STATUS_PRINTER_PAPER_STALL,
  89.                    'penf' : STATUS_PRINTER_PEN_FAILURE,
  90.                    'erro' : STATUS_PRINTER_HARD_ERROR,
  91.                    'pwdn' : STATUS_PRINTER_POWER_DOWN,
  92.                    'fpts' : STATUS_PRINTER_FRONT_PANEL_TEST,
  93.                    'clno' : STATUS_PRINTER_CLEAN_OUT_TRAY_MISSING}
  94.  
  95. REVISION_2_TYPE_MAP = {0 : AGENT_TYPE_NONE,
  96.                         1 : AGENT_TYPE_BLACK,
  97.                         2 : AGENT_TYPE_CYAN,
  98.                         3 : AGENT_TYPE_MAGENTA,
  99.                         4 : AGENT_TYPE_YELLOW,
  100.                         5 : AGENT_TYPE_BLACK,
  101.                         6 : AGENT_TYPE_CYAN,
  102.                         7 : AGENT_TYPE_MAGENTA,
  103.                         8 : AGENT_TYPE_YELLOW,
  104.                        }
  105.  
  106. STATUS_BLOCK_UNKNOWN = {'revision' : STATUS_REV_UNKNOWN,
  107.                          'agents' : [],
  108.                          'status-code' : STATUS_UNKNOWN,
  109.                        }
  110.  
  111. NUM_PEN_POS = {STATUS_REV_00 : 16,
  112.                 STATUS_REV_01 : 16,
  113.                 STATUS_REV_02 : 16,
  114.                 STATUS_REV_03 : 18,
  115.                 STATUS_REV_04 : 22}
  116.  
  117. PEN_DATA_SIZE = {STATUS_REV_00 : 8,
  118.                   STATUS_REV_01 : 8,
  119.                   STATUS_REV_02 : 4,
  120.                   STATUS_REV_03 : 8,
  121.                   STATUS_REV_04 : 8}
  122.  
  123. STATUS_POS = {STATUS_REV_00 : 14,
  124.                STATUS_REV_01 : 14,
  125.                STATUS_REV_02 : 14,
  126.                STATUS_REV_03 : 16,
  127.                STATUS_REV_04 : 20}
  128.  
  129. def parseSStatus(s, z=''):
  130.     revision = ''
  131.     pens = []
  132.     top_door = TOP_DOOR_NOT_PRESENT
  133.     stat = STATUS_UNKNOWN
  134.     supply_door = SUPPLY_DOOR_NOT_PRESENT
  135.     duplexer = DUPLEXER_NOT_PRESENT
  136.     photo_tray = PHOTO_TRAY_NOT_PRESENT
  137.     in_tray1 = IN_TRAY_NOT_PRESENT
  138.     in_tray2 = IN_TRAY_NOT_PRESENT
  139.     media_path = MEDIA_PATH_NOT_PRESENT
  140.     Z_SIZE = 6
  141.  
  142.     try:
  143.         z1 = []
  144.         if len(z) > 0:
  145.             z_fields = z.split(',')
  146.  
  147.             for z_field in z_fields:
  148.  
  149.                 if len(z_field) > 2 and z_field[:2] == '05':
  150.                     z1s = z_field[2:]
  151.                     z1 = [int(x, 16) for x in z1s]
  152.  
  153.         s1 = [int(x, 16) for x in s]
  154.  
  155.         revision = s1[1]
  156.  
  157.         assert STATUS_REV_00 <= revision <= STATUS_REV_04
  158.  
  159.         top_door = bool(s1[2] & 0x8L) + s1[2] & 0x1L
  160.         supply_door = bool(s1[3] & 0x8L) + s1[3] & 0x1L
  161.         duplexer = bool(s1[4] & 0xcL) +  s1[4] & 0x1L
  162.         photo_tray = bool(s1[5] & 0x8L) + s1[5] & 0x1L
  163.  
  164.         if revision == STATUS_REV_02:
  165.             in_tray1 = bool(s1[6] & 0x8L) + s1[6] & 0x1L
  166.             in_tray2 = bool(s1[7] & 0x8L) + s1[7] & 0x1L
  167.         else:
  168.             in_tray1 = bool(s1[6] & 0x8L)
  169.             in_tray2 = bool(s1[7] & 0x8L)
  170.  
  171.         media_path = bool(s1[8] & 0x8L) + (s1[8] & 0x1L) + ((bool(s1[18] & 0x2L))<<1)
  172.         status_pos = STATUS_POS[revision]
  173.         status_byte = (s1[status_pos]<<4) + s1[status_pos + 1]
  174.         stat = status_byte + STATUS_PRINTER_BASE
  175.  
  176.         pen, c, d = {}, NUM_PEN_POS[revision]+1, 0
  177.         num_pens = s1[NUM_PEN_POS[revision]]
  178.         log.debug("Num pens=%d" % num_pens)
  179.         index = 0
  180.         pen_data_size = PEN_DATA_SIZE[revision]
  181.  
  182.         for p in range(num_pens):
  183.             info = long(s[c : c + pen_data_size], 16)
  184.  
  185.             pen['index'] = index
  186.  
  187.             if pen_data_size == 4:
  188.                 pen['type'] = REVISION_2_TYPE_MAP.get(int((info & 0xf000L) >> 12L), 0)
  189.  
  190.                 if index < (num_pens / 2):
  191.                     pen['kind'] = AGENT_KIND_HEAD
  192.                 else:
  193.                     pen['kind'] = AGENT_KIND_SUPPLY
  194.  
  195.                 pen['level-trigger'] = int ((info & 0x0e00L) >> 9L)
  196.                 pen['health'] = int((info & 0x0180L) >> 7L)
  197.                 pen['level'] = int(info & 0x007fL)
  198.                 pen['id'] = 0x1f
  199.  
  200.             elif pen_data_size == 8:
  201.                 pen['kind'] = bool(info & 0x80000000L) + ((bool(info & 0x40000000L))<<1L)
  202.                 pen['type'] = int((info & 0x3f000000L) >> 24L)
  203.                 pen['id'] = int((info & 0xf80000) >> 19L)
  204.                 pen['level-trigger'] = int((info & 0x70000L) >> 16L)
  205.                 pen['health'] = int((info & 0xc000L) >> 14L)
  206.                 pen['level'] = int(info & 0xffL)
  207.  
  208.             else:
  209.                 log.error("Pen data size error")
  210.  
  211.             if len(z1) > 0:
  212.                 # TODO: Determine cause of IndexError for C6100 (defect #1111)
  213.                 try:
  214.                     pen['dvc'] = long(z1s[d+1:d+5], 16)
  215.                     pen['virgin'] = bool(z1[d+5] & 0x8L)
  216.                     pen['hp-ink'] = bool(z1[d+5] & 0x4L)
  217.                     pen['known'] = bool(z1[d+5] & 0x2L)
  218.                     pen['ack'] = bool(z1[d+5] & 0x1L)
  219.                 except IndexError:
  220.                     pen['dvc'] = 0
  221.                     pen['virgin'] = 0
  222.                     pen['hp-ink'] = 0
  223.                     pen['known'] = 0
  224.                     pen['ack'] = 0
  225.  
  226.             index += 1
  227.             pens.append(pen)
  228.             log.debug("Pen %d: %s" % (p, pen))
  229.             pen = {}
  230.             c += pen_data_size
  231.             d += Z_SIZE
  232.  
  233.     except (IndexError, ValueError, TypeError), e:
  234.         log.warn("Status parsing error: %s" % str(e))
  235.  
  236.     return {'revision' :    revision,
  237.              'agents' :      pens,
  238.              'top-door' :    top_door,
  239.              'status-code' : stat,
  240.              'supply-door' : supply_door,
  241.              'duplexer' :    duplexer,
  242.              'photo-tray' :  photo_tray,
  243.              'in-tray1' :    in_tray1,
  244.              'in-tray2' :    in_tray2,
  245.              'media-path' :  media_path,
  246.            }
  247.  
  248.  
  249.  
  250. # $HB0$NC0,ff,DN,IDLE,CUT,K0,C0,DP,NR,KP092,CP041
  251. #     0    1  2  3    4   5  6  7  8  9     10
  252. def parseVStatus(s):
  253.     pens, pen, c = [], {}, 0
  254.     fields = s.split(',')
  255.     log.debug(fields)
  256.     f0 = fields[0]
  257.  
  258.     if len(f0) == 20:
  259.         # TODO: $H00000000$M00000000 style (OJ Pro 1150/70)
  260.         # Need spec
  261.         pass
  262.     elif len(f0) == 8:
  263.         for p in f0:
  264.             if c == 0:
  265.                 #assert p == '$'
  266.                 c += 1
  267.             elif c == 1:
  268.                 if p in ('a', 'A'):
  269.                     pen['type'], pen['kind'] = AGENT_TYPE_NONE, AGENT_KIND_NONE
  270.                 c += 1
  271.             elif c == 2:
  272.                 pen['health'] = AGENT_HEALTH_OK
  273.                 pen['kind'] = AGENT_KIND_HEAD_AND_SUPPLY
  274.                 if   p in ('b', 'B'): pen['type'] = AGENT_TYPE_BLACK
  275.                 elif p in ('c', 'C'): pen['type'] = AGENT_TYPE_CMY
  276.                 elif p in ('d', 'D'): pen['type'] = AGENT_TYPE_KCM
  277.                 elif p in ('u', 'U'): pen['type'], pen['health'] = AGENT_TYPE_NONE, AGENT_HEALTH_MISINSTALLED
  278.                 c += 1
  279.             elif c == 3:
  280.                 if p == '0': pen['state'] = 1
  281.                 else: pen['state'] = 0
  282.  
  283.                 pen['level'] = 0
  284.                 i = 8
  285.  
  286.                 while True:
  287.                     try:
  288.                         f = fields[i]
  289.                     except IndexError:
  290.                         break
  291.                     else:
  292.                         if f[:2] == 'KP' and pen['type'] == AGENT_TYPE_BLACK:
  293.                             pen['level'] = int(f[2:])
  294.                         elif f[:2] == 'CP' and pen['type'] == AGENT_TYPE_CMY:
  295.                             pen['level'] = int(f[2:])
  296.                     i += 1
  297.  
  298.                 pens.append(pen)
  299.                 pen = {}
  300.                 c = 0
  301.     else:
  302.         pass
  303.  
  304.     try:
  305.         fields[2]
  306.     except IndexError:
  307.         top_lid = 1 # something went wrong!
  308.     else:
  309.         if fields[2] == 'DN':
  310.             top_lid = 1
  311.         else:
  312.             top_lid = 2
  313.  
  314.     try:
  315.         stat = vstatus_xlate.get(fields[3].lower(), STATUS_PRINTER_IDLE)
  316.     except IndexError:
  317.         stat = STATUS_PRINTER_IDLE # something went wrong!
  318.  
  319.     return {'revision' :   STATUS_REV_V,
  320.              'agents' :     pens,
  321.              'top-door' :   top_lid,
  322.              'status-code': stat,
  323.              'supply-door': SUPPLY_DOOR_NOT_PRESENT,
  324.              'duplexer' :   DUPLEXER_NOT_PRESENT,
  325.              'photo-tray' : PHOTO_TRAY_NOT_PRESENT,
  326.              'in-tray1' :   IN_TRAY_NOT_PRESENT,
  327.              'in-tray2' :   IN_TRAY_NOT_PRESENT,
  328.              'media-path' : MEDIA_PATH_CUT_SHEET, # ?
  329.            }
  330.  
  331.  
  332. def parseStatus(DeviceID):
  333.     if 'VSTATUS' in DeviceID:
  334.          return parseVStatus(DeviceID['VSTATUS'])
  335.     elif 'S' in DeviceID:
  336.         return parseSStatus(DeviceID['S'], DeviceID.get('Z', ''))
  337.     else:
  338.         return STATUS_BLOCK_UNKNOWN
  339.  
  340.  
  341.  
  342. def LaserJetDeviceStatusToPrinterStatus(device_status, printer_status, detected_error_state):
  343.     stat = STATUS_PRINTER_IDLE
  344.  
  345.     if device_status in (pml.DEVICE_STATUS_WARNING, pml.DEVICE_STATUS_DOWN):
  346.  
  347.         if detected_error_state & pml.DETECTED_ERROR_STATE_LOW_PAPER_MASK and \
  348.             not (detected_error_state & pml.DETECTED_ERROR_STATE_NO_PAPER_MASK):
  349.             stat = STATUS_PRINTER_LOW_PAPER
  350.  
  351.         elif detected_error_state & pml.DETECTED_ERROR_STATE_NO_PAPER_MASK:
  352.             stat = STATUS_PRINTER_OUT_OF_PAPER
  353.  
  354.         elif detected_error_state & pml.DETECTED_ERROR_STATE_DOOR_OPEN_MASK:
  355.             stat = STATUS_PRINTER_DOOR_OPEN
  356.  
  357.         elif detected_error_state & pml.DETECTED_ERROR_STATE_JAMMED_MASK:
  358.             stat = STATUS_PRINTER_MEDIA_JAM
  359.  
  360.         elif detected_error_state & pml.DETECTED_ERROR_STATE_OUT_CART_MASK:
  361.             stat = STATUS_PRINTER_NO_TONER
  362.  
  363.         elif detected_error_state & pml.DETECTED_ERROR_STATE_LOW_CART_MASK:
  364.             stat = STATUS_PRINTER_LOW_TONER
  365.  
  366.         elif detected_error_state == pml.DETECTED_ERROR_STATE_SERVICE_REQUEST_MASK:
  367.             stat = STATUS_PRINTER_SERVICE_REQUEST
  368.  
  369.         elif detected_error_state & pml.DETECTED_ERROR_STATE_OFFLINE_MASK:
  370.             stat = STATUS_PRINTER_OFFLINE
  371.  
  372.     else:
  373.  
  374.         if printer_status == pml.PRINTER_STATUS_IDLE:
  375.             stat = STATUS_PRINTER_IDLE
  376.  
  377.         elif printer_status == pml.PRINTER_STATUS_PRINTING:
  378.             stat = STATUS_PRINTER_PRINTING
  379.  
  380.         elif printer_status == pml.PRINTER_STATUS_WARMUP:
  381.             stat = STATUS_PRINTER_WARMING_UP
  382.  
  383.     return stat
  384.  
  385. # Map from ISO 10175/10180 to HPLIP types
  386. COLORANT_INDEX_TO_AGENT_TYPE_MAP = {
  387.                                     'other' :   AGENT_TYPE_UNSPECIFIED,
  388.                                     'unknown' : AGENT_TYPE_UNSPECIFIED,
  389.                                     'blue' :    AGENT_TYPE_BLUE,
  390.                                     'cyan' :    AGENT_TYPE_CYAN,
  391.                                     'magenta':  AGENT_TYPE_MAGENTA,
  392.                                     'yellow' :  AGENT_TYPE_YELLOW,
  393.                                     'black' :   AGENT_TYPE_BLACK,
  394.                                    }
  395.  
  396. MARKER_SUPPLES_TYPE_TO_AGENT_KIND_MAP = {
  397.     pml.OID_MARKER_SUPPLIES_TYPE_OTHER :              AGENT_KIND_UNKNOWN,
  398.     pml.OID_MARKER_SUPPLIES_TYPE_UNKNOWN :            AGENT_KIND_UNKNOWN,
  399.     pml.OID_MARKER_SUPPLIES_TYPE_TONER :              AGENT_KIND_TONER_CARTRIDGE,
  400.     pml.OID_MARKER_SUPPLIES_TYPE_WASTE_TONER :        AGENT_KIND_UNKNOWN,
  401.     pml.OID_MARKER_SUPPLIES_TYPE_INK :                AGENT_KIND_SUPPLY,
  402.     pml.OID_MARKER_SUPPLIES_TYPE_INK_CART :           AGENT_KIND_HEAD_AND_SUPPLY,
  403.     pml.OID_MARKER_SUPPLIES_TYPE_INK_RIBBON :         AGENT_KIND_HEAD_AND_SUPPLY,
  404.     pml.OID_MARKER_SUPPLIES_TYPE_WASTE_INK :          AGENT_KIND_UNKNOWN,
  405.     pml.OID_MARKER_SUPPLIES_TYPE_OPC :                AGENT_KIND_DRUM_KIT,
  406.     pml.OID_MARKER_SUPPLIES_TYPE_DEVELOPER :          AGENT_KIND_UNKNOWN,
  407.     pml.OID_MARKER_SUPPLIES_TYPE_FUSER_OIL :          AGENT_KIND_UNKNOWN,
  408.     pml.OID_MARKER_SUPPLIES_TYPE_SOLID_WAX :          AGENT_KIND_UNKNOWN,
  409.     pml.OID_MARKER_SUPPLIES_TYPE_RIBBON_WAX :         AGENT_KIND_UNKNOWN,
  410.     pml.OID_MARKER_SUPPLIES_TYPE_WASTE_WAX :          AGENT_KIND_UNKNOWN,
  411.     pml.OID_MARKER_SUPPLIES_TYPE_FUSER :              AGENT_KIND_MAINT_KIT,
  412.     pml.OID_MARKER_SUPPLIES_TYPE_CORONA_WIRE :        AGENT_KIND_UNKNOWN,
  413.     pml.OID_MARKER_SUPPLIES_TYPE_FUSER_OIL_WICK :     AGENT_KIND_UNKNOWN,
  414.     pml.OID_MARKER_SUPPLIES_TYPE_CLEANER_UNIT :       AGENT_KIND_UNKNOWN,
  415.     pml.OID_MARKER_SUPPLIES_TYPE_FUSER_CLEANING_PAD : AGENT_KIND_UNKNOWN,
  416.     pml.OID_MARKER_SUPPLIES_TYPE_TRANSFER_UNIT :      AGENT_KIND_TRANSFER_KIT,
  417.     pml.OID_MARKER_SUPPLIES_TYPE_TONER_CART :         AGENT_KIND_TONER_CARTRIDGE,
  418.     pml.OID_MARKER_SUPPLIES_TYPE_FUSER_OILER :        AGENT_KIND_UNKNOWN,
  419.     pml.OID_MARKER_SUPPLIES_TYPE_ADF_MAINT_KIT :      AGENT_KIND_ADF_KIT,
  420. }
  421.  
  422.  
  423. def StatusType3( dev, parsedID ): # LaserJet Status (PML/SNMP)
  424.     try:
  425.         dev.openPML()
  426.         #result_code, on_off_line = dev.getPML( pml.OID_ON_OFF_LINE, pml.INT_SIZE_BYTE )
  427.         #result_code, sleep_mode = dev.getPML( pml.OID_SLEEP_MODE, pml.INT_SIZE_BYTE )
  428.         result_code, printer_status = dev.getPML( pml.OID_PRINTER_STATUS, pml.INT_SIZE_BYTE )
  429.         result_code, device_status = dev.getPML( pml.OID_DEVICE_STATUS, pml.INT_SIZE_BYTE )
  430.         result_code, cover_status = dev.getPML( pml.OID_COVER_STATUS, pml.INT_SIZE_BYTE )
  431.         result_code, value = dev.getPML( pml.OID_DETECTED_ERROR_STATE )
  432.     except Error:
  433.        dev.closePML()
  434.  
  435.        return {'revision' :    STATUS_REV_UNKNOWN,
  436.                  'agents' :      [],
  437.                  'top-door' :    0,
  438.                  'status-code' : STATUS_UNKNOWN,
  439.                  'supply-door' : 0,
  440.                  'duplexer' :    1,
  441.                  'photo-tray' :  0,
  442.                  'in-tray1' :    0,
  443.                  'in-tray2' :    0,
  444.                  'media-path' :  0,
  445.                }
  446.  
  447.     try:
  448.         detected_error_state = struct.unpack( 'B', value[0])[0]
  449.     except (IndexError, TypeError):
  450.         detected_error_state = pml.DETECTED_ERROR_STATE_OFFLINE_MASK
  451.  
  452.     agents, x = [], 1
  453.  
  454.     while True:
  455.         log.debug( "%s Agent: %d %s" % ("*"*10, x, "*"*10))
  456.         log.debug("OID_MARKER_SUPPLIES_TYPE_%d:" % x)
  457.         oid = ( pml.OID_MARKER_SUPPLIES_TYPE_x % x, pml.OID_MARKER_SUPPLIES_TYPE_x_TYPE )
  458.         result_code, value = dev.getPML( oid, pml.INT_SIZE_BYTE )
  459.  
  460.         if result_code != ERROR_SUCCESS or value is None:
  461.             log.debug("End of supply information.")
  462.             break
  463.  
  464.         for a in MARKER_SUPPLES_TYPE_TO_AGENT_KIND_MAP:
  465.             if value == a:
  466.                 agent_kind = MARKER_SUPPLES_TYPE_TO_AGENT_KIND_MAP[a]
  467.                 break
  468.         else:
  469.             agent_kind = AGENT_KIND_UNKNOWN
  470.  
  471.         # TODO: Deal with printers that return -1 and -2 for level and max (LJ3380)
  472.  
  473.         log.debug("OID_MARKER_SUPPLIES_LEVEL_%d:" % x)
  474.         oid = ( pml.OID_MARKER_SUPPLIES_LEVEL_x % x, pml.OID_MARKER_SUPPLIES_LEVEL_x_TYPE )
  475.         result_code, agent_level = dev.getPML( oid )
  476.  
  477.         if result_code != ERROR_SUCCESS:
  478.             log.debug("Failed")
  479.             break
  480.  
  481.         log.debug( 'agent%d-level: %d' % ( x, agent_level ) )
  482.         log.debug("OID_MARKER_SUPPLIES_MAX_%d:" % x)
  483.         oid = ( pml.OID_MARKER_SUPPLIES_MAX_x % x, pml.OID_MARKER_SUPPLIES_MAX_x_TYPE )
  484.         result_code, agent_max = dev.getPML( oid )
  485.  
  486.         if agent_max == 0: agent_max = 1
  487.  
  488.         if result_code != ERROR_SUCCESS:
  489.             log.debug("Failed")
  490.             break
  491.  
  492.         log.debug( 'agent%d-max: %d' % ( x, agent_max ) )
  493.         log.debug("OID_MARKER_SUPPLIES_COLORANT_INDEX_%d:" % x)
  494.         oid = ( pml.OID_MARKER_SUPPLIES_COLORANT_INDEX_x % x, pml.OID_MARKER_SUPPLIES_COLORANT_INDEX_x_TYPE )
  495.         result_code, colorant_index = dev.getPML( oid )
  496.  
  497.         if result_code != ERROR_SUCCESS: # 3080, 3055 will fail here
  498.             log.debug("Failed")
  499.             agent_type = AGENT_TYPE_BLACK
  500.             #break
  501.         else:
  502.             log.debug("Colorant index: %d" % colorant_index)
  503.  
  504.             log.debug("OID_MARKER_COLORANT_VALUE_%d" % x)
  505.             oid = ( pml.OID_MARKER_COLORANT_VALUE_x % colorant_index, pml.OID_MARKER_COLORANT_VALUE_x_TYPE )
  506.             result_code, colorant_value = dev.getPML( oid )
  507.  
  508.             if result_code != ERROR_SUCCESS:
  509.                 log.debug("Failed. Defaulting to black.")
  510.                 agent_type = AGENT_TYPE_BLACK
  511.             #else:
  512.             if 1:
  513.                 if agent_kind in (AGENT_KIND_MAINT_KIT, AGENT_KIND_ADF_KIT,
  514.                                   AGENT_KIND_DRUM_KIT, AGENT_KIND_TRANSFER_KIT):
  515.  
  516.                     agent_type = AGENT_TYPE_UNSPECIFIED
  517.  
  518.                 else:
  519.                     agent_type = AGENT_TYPE_BLACK
  520.  
  521.                     if result_code != ERROR_SUCCESS:
  522.                         log.debug("OID_MARKER_SUPPLIES_DESCRIPTION_%d:" % x)
  523.                         oid = (pml.OID_MARKER_SUPPLIES_DESCRIPTION_x % x, pml.OID_MARKER_SUPPLIES_DESCRIPTION_x_TYPE)
  524.                         result_code, colorant_value = dev.getPML( oid )
  525.  
  526.                         if result_code != ERROR_SUCCESS:
  527.                             log.debug("Failed")
  528.                             break
  529.  
  530.                         if colorant_value is not None:
  531.                             log.debug("colorant value: %s" % colorant_value)
  532.                             colorant_value = colorant_value.lower().strip()
  533.  
  534.                             for c in COLORANT_INDEX_TO_AGENT_TYPE_MAP:
  535.                                 if colorant_value.find(c) >= 0:
  536.                                     agent_type = COLORANT_INDEX_TO_AGENT_TYPE_MAP[c]
  537.                                     break
  538.                             else:
  539.                                 agent_type = AGENT_TYPE_BLACK
  540.  
  541.                     else: # SUCCESS
  542.                         if colorant_value is not None:
  543.                             log.debug("colorant value: %s" % colorant_value)
  544.                             agent_type = COLORANT_INDEX_TO_AGENT_TYPE_MAP.get( colorant_value, AGENT_TYPE_BLACK )
  545.  
  546.                         if agent_type == AGENT_TYPE_NONE:
  547.                             if agent_kind == AGENT_KIND_TONER_CARTRIDGE:
  548.                                 agent_type = AGENT_TYPE_BLACK
  549.                             else:
  550.                                 agent_type = AGENT_TYPE_UNSPECIFIED
  551.  
  552.         log.debug("OID_MARKER_STATUS_%d:" % x)
  553.         oid = ( pml.OID_MARKER_STATUS_x % x, pml.OID_MARKER_STATUS_x_TYPE )
  554.         result_code, agent_status = dev.getPML( oid )
  555.  
  556.         if result_code != ERROR_SUCCESS:
  557.             log.debug("Failed")
  558.             agent_trigger = AGENT_LEVEL_TRIGGER_SUFFICIENT_0
  559.             agent_health = AGENT_HEALTH_OK
  560.         else:
  561.             agent_trigger = AGENT_LEVEL_TRIGGER_SUFFICIENT_0
  562.  
  563.             if agent_status is None:
  564.                 agent_health = AGENT_HEALTH_OK
  565.  
  566.             elif agent_status == pml.OID_MARKER_STATUS_OK:
  567.                 agent_health = AGENT_HEALTH_OK
  568.  
  569.             elif agent_status == pml.OID_MARKER_STATUS_MISINSTALLED:
  570.                 agent_health = AGENT_HEALTH_MISINSTALLED
  571.  
  572.             elif agent_status in ( pml.OID_MARKER_STATUS_LOW_TONER_CONT,
  573.                                    pml.OID_MARKER_STATUS_LOW_TONER_STOP ):
  574.  
  575.                 agent_health = AGENT_HEALTH_OK
  576.                 agent_trigger = AGENT_LEVEL_TRIGGER_MAY_BE_LOW
  577.  
  578.             else:
  579.                 agent_health = AGENT_HEALTH_OK
  580.  
  581.         agent_level = int(agent_level/agent_max * 100)
  582.  
  583.         log.debug("agent%d: kind=%d, type=%d, health=%d, level=%d, level-trigger=%d" % \
  584.             (x, agent_kind, agent_type, agent_health, agent_level, agent_trigger))
  585.  
  586.  
  587.         agents.append({'kind' : agent_kind,
  588.                        'type' : agent_type,
  589.                        'health' : agent_health,
  590.                        'level' : agent_level,
  591.                        'level-trigger' : agent_trigger,})
  592.  
  593.         x += 1
  594.  
  595.         if x > 20:
  596.             break
  597.  
  598.  
  599.     printer_status = printer_status or STATUS_PRINTER_IDLE
  600.     log.debug("printer_status=%d" % printer_status)
  601.     device_status = device_status or pml.DEVICE_STATUS_RUNNING
  602.     log.debug("device_status=%d" % device_status)
  603.     cover_status = cover_status or pml.COVER_STATUS_CLOSED
  604.     log.debug("cover_status=%d" % cover_status)
  605.     detected_error_state = detected_error_state or pml.DETECTED_ERROR_STATE_NO_ERROR
  606.     log.debug("detected_error_state=%d (0x%x)" % (detected_error_state, detected_error_state))
  607.  
  608.     stat = LaserJetDeviceStatusToPrinterStatus(device_status, printer_status, detected_error_state)
  609.  
  610.     log.debug("Printer status=%d" % stat)
  611.  
  612.     if stat == STATUS_PRINTER_DOOR_OPEN:
  613.         supply_door = 0
  614.     else:
  615.         supply_door = 1
  616.  
  617.     return {'revision' :    STATUS_REV_UNKNOWN,
  618.              'agents' :      agents,
  619.              'top-door' :    cover_status,
  620.              'status-code' : stat,
  621.              'supply-door' : supply_door,
  622.              'duplexer' :    1,
  623.              'photo-tray' :  0,
  624.              'in-tray1' :    1,
  625.              'in-tray2' :    1,
  626.              'media-path' :  1,
  627.            }
  628.  
  629. def setup_panel_translator():
  630.     printables = list(
  631. """0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
  632. !"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~""")
  633.  
  634.     map = {}
  635.     for x in [chr(x) for x in range(0,256)]:
  636.         if x in printables:
  637.             map[x] = x
  638.         else:
  639.             map[x] = '\x20'
  640.  
  641.     map.update({'\x10' : '\xab',
  642.                     '\x11' : '\xbb',
  643.                     '\x12' : '\xa3',
  644.                     '\x13' : '\xbb',
  645.                     '\x80' : '\xab',
  646.                     '\x81' : '\xbb',
  647.                     '\x82' : '\x2a',
  648.                     '\x83' : '\x2a',
  649.                     '\x85' : '\x2a',
  650.                     '\xa0' : '\xab',
  651.                     '\x1f' : '\x3f',
  652.                     '='    : '\x20',
  653.                 })
  654.  
  655.     frm, to = '', ''
  656.     map_keys = map.keys()
  657.     map_keys.sort()
  658.     for x in map_keys:
  659.         frm = ''.join([frm, x])
  660.         to = ''.join([to, map[x]])
  661.  
  662.     global PANEL_TRANSLATOR_FUNC
  663.     PANEL_TRANSLATOR_FUNC = utils.Translator(frm, to)
  664.  
  665. PANEL_TRANSLATOR_FUNC = None
  666. setup_panel_translator()
  667.  
  668.  
  669. def PanelCheck(dev):
  670.     line1, line2 = '', ''
  671.  
  672.     if dev.io_mode not in (IO_MODE_RAW, IO_MODE_UNI):
  673.  
  674.         try:
  675.             dev.openPML()
  676.         except Error:
  677.             pass
  678.         else:
  679.  
  680.             oids = [(pml.OID_HP_LINE1, pml.OID_HP_LINE2),
  681.                      (pml.OID_SPM_LINE1, pml.OID_SPM_LINE2)]
  682.  
  683.             for oid1, oid2 in oids:
  684.                 result, line1 = dev.getPML(oid1)
  685.  
  686.                 if result < pml.ERROR_MAX_OK:
  687.                     line1 = PANEL_TRANSLATOR_FUNC(line1).rstrip()
  688.  
  689.                     if '\x0a' in line1:
  690.                         line1, line2 = line1.split('\x0a', 1)
  691.                         break
  692.  
  693.                     result, line2 = dev.getPML(oid2)
  694.  
  695.                     if result < pml.ERROR_MAX_OK:
  696.                         line2 = PANEL_TRANSLATOR_FUNC(line2).rstrip()
  697.                         break
  698.  
  699.     return bool(line1 or line2), line1 or '', line2 or ''
  700.  
  701.  
  702. BATTERY_HEALTH_MAP = {0 : AGENT_HEALTH_OK,
  703.                        1 : AGENT_HEALTH_OVERTEMP,
  704.                        2 : AGENT_HEALTH_CHARGING,
  705.                        3 : AGENT_HEALTH_MISINSTALLED,
  706.                        4 : AGENT_HEALTH_FAILED,
  707.                       }
  708.  
  709.  
  710. BATTERY_TRIGGER_MAP = {0 : AGENT_LEVEL_TRIGGER_SUFFICIENT_0,
  711.                         1 : AGENT_LEVEL_TRIGGER_ALMOST_DEFINITELY_OUT,
  712.                         2 : AGENT_LEVEL_TRIGGER_PROBABLY_OUT,
  713.                         3 : AGENT_LEVEL_TRIGGER_SUFFICIENT_4,
  714.                         4 : AGENT_LEVEL_TRIGGER_SUFFICIENT_2,
  715.                         5 : AGENT_LEVEL_TRIGGER_SUFFICIENT_0,
  716.                        }
  717.  
  718. BATTERY_PML_TRIGGER_MAP = {
  719.         (100, 80)  : AGENT_LEVEL_TRIGGER_SUFFICIENT_0,
  720.         (79,  60)  : AGENT_LEVEL_TRIGGER_SUFFICIENT_1,
  721.         (59,  40)  : AGENT_LEVEL_TRIGGER_SUFFICIENT_2,
  722.         (39,  30)  : AGENT_LEVEL_TRIGGER_SUFFICIENT_3,
  723.         (29,  20)  : AGENT_LEVEL_TRIGGER_SUFFICIENT_4,
  724.         (19,  10)  : AGENT_LEVEL_TRIGGER_MAY_BE_LOW,
  725.         (9,    5)  : AGENT_LEVEL_TRIGGER_PROBABLY_OUT,
  726.         (4,   -1)  : AGENT_LEVEL_TRIGGER_ALMOST_DEFINITELY_OUT,
  727.         }
  728.  
  729.  
  730. def BatteryCheck(dev, status_block, battery_check):
  731.     try_dynamic_counters = False
  732.  
  733.     try:
  734.         try:
  735.             dev.openPML()
  736.         except Error:
  737.             if battery_check == STATUS_BATTERY_CHECK_STD:
  738.                 log.debug("PML channel open failed. Trying dynamic counters...")
  739.                 try_dynamic_counters = True
  740.         else:
  741.             if battery_check == STATUS_BATTERY_CHECK_PML:
  742.                 result, battery_level = dev.getPML(pml.OID_BATTERY_LEVEL_2)
  743.  
  744.                 if result > pml.ERROR_MAX_OK:
  745.                     status_block['agents'].append({
  746.                         'kind'   : AGENT_KIND_INT_BATTERY,
  747.                         'type'   : AGENT_TYPE_UNSPECIFIED,
  748.                         'health' : AGENT_HEALTH_UNKNOWN,
  749.                         'level'  : 0,
  750.                         'level-trigger' : AGENT_LEVEL_TRIGGER_SUFFICIENT_0,
  751.                         })
  752.                     return
  753.  
  754.                 else:
  755.                     status_block['agents'].append({
  756.                         'kind'   : AGENT_KIND_INT_BATTERY,
  757.                         'type'   : AGENT_TYPE_UNSPECIFIED,
  758.                         'health' : AGENT_HEALTH_OK,
  759.                         'level'  : battery_level,
  760.                         'level-trigger' : AGENT_LEVEL_TRIGGER_SUFFICIENT_0,
  761.                         })
  762.                     return
  763.  
  764.             else: # STATUS_BATTERY_CHECK_STD
  765.                 result, battery_level = dev.getPML(pml.OID_BATTERY_LEVEL)
  766.                 result, power_mode =  dev.getPML(pml.OID_POWER_MODE)
  767.  
  768.                 if battery_level is not None and \
  769.                     power_mode is not None:
  770.  
  771.                     if power_mode & pml.POWER_MODE_BATTERY_LEVEL_KNOWN and \
  772.                         battery_level >= 0:
  773.  
  774.                         for x in BATTERY_PML_TRIGGER_MAP:
  775.                             if x[0] >= battery_level > x[1]:
  776.                                 battery_trigger_level = BATTERY_PML_TRIGGER_MAP[x]
  777.                                 break
  778.  
  779.                         if power_mode & pml.POWER_MODE_CHARGING:
  780.                             agent_health = AGENT_HEALTH_CHARGING
  781.  
  782.                         elif power_mode & pml.POWER_MODE_DISCHARGING:
  783.                             agent_health = AGENT_HEALTH_DISCHARGING
  784.  
  785.                         else:
  786.                             agent_health = AGENT_HEALTH_OK
  787.  
  788.                         status_block['agents'].append({
  789.                             'kind'   : AGENT_KIND_INT_BATTERY,
  790.                             'type'   : AGENT_TYPE_UNSPECIFIED,
  791.                             'health' : agent_health,
  792.                             'level'  : battery_level,
  793.                             'level-trigger' : battery_trigger_level,
  794.                             })
  795.                         return
  796.  
  797.                     else:
  798.                         status_block['agents'].append({
  799.                             'kind'   : AGENT_KIND_INT_BATTERY,
  800.                             'type'   : AGENT_TYPE_UNSPECIFIED,
  801.                             'health' : AGENT_HEALTH_UNKNOWN,
  802.                             'level'  : 0,
  803.                             'level-trigger' : AGENT_LEVEL_TRIGGER_SUFFICIENT_0,
  804.                             })
  805.                         return
  806.  
  807.                 else:
  808.                     try_dynamic_counters = True
  809.  
  810.     finally:
  811.         dev.closePML()
  812.  
  813.  
  814.     if battery_check == STATUS_BATTERY_CHECK_STD and \
  815.         try_dynamic_counters:
  816.  
  817.         try:
  818.             try:
  819.                 battery_health = dev.getDynamicCounter(200)
  820.                 battery_trigger_level = dev.getDynamicCounter(201)
  821.                 battery_level = dev.getDynamicCounter(202)
  822.  
  823.                 status_block['agents'].append({
  824.                     'kind'   : AGENT_KIND_INT_BATTERY,
  825.                     'type'   : AGENT_TYPE_UNSPECIFIED,
  826.                     'health' : BATTERY_HEALTH_MAP[battery_health],
  827.                     'level'  : battery_level,
  828.                     'level-trigger' : BATTERY_TRIGGER_MAP[battery_trigger_level],
  829.                     })
  830.             except Error:
  831.                 status_block['agents'].append({
  832.                     'kind'   : AGENT_KIND_INT_BATTERY,
  833.                     'type'   : AGENT_TYPE_UNSPECIFIED,
  834.                     'health' : AGENT_HEALTH_UNKNOWN,
  835.                     'level'  : 0,
  836.                     'level-trigger' : AGENT_LEVEL_TRIGGER_SUFFICIENT_0,
  837.                     })
  838.         finally:
  839.             dev.closePrint()
  840.  
  841.     else:
  842.         status_block['agents'].append({
  843.             'kind'   : AGENT_KIND_INT_BATTERY,
  844.             'type'   : AGENT_TYPE_UNSPECIFIED,
  845.             'health' : AGENT_HEALTH_UNKNOWN,
  846.             'level'  : 0,
  847.             'level-trigger' : AGENT_LEVEL_TRIGGER_SUFFICIENT_0,
  848.             })
  849.  
  850.  
  851.  
  852. # this works for 2 pen products that allow 1 or 2 pens inserted
  853. # from: k, kcm, cmy, ggk
  854. def getPenConfiguration(s): # s=status dict from parsed device ID
  855.     pens = [p['type'] for p in s['agents']]
  856.  
  857.     if utils.all(pens, lambda x : x==AGENT_TYPE_NONE):
  858.         return AGENT_CONFIG_NONE
  859.  
  860.     if AGENT_TYPE_NONE in pens:
  861.  
  862.         if AGENT_TYPE_BLACK in pens:
  863.             return AGENT_CONFIG_BLACK_ONLY
  864.  
  865.         elif AGENT_TYPE_CMY in pens:
  866.             return AGENT_CONFIG_COLOR_ONLY
  867.  
  868.         elif AGENT_TYPE_KCM in pens:
  869.             return AGENT_CONFIG_PHOTO_ONLY
  870.  
  871.         elif AGENT_TYPE_GGK in pens:
  872.             return AGENT_CONFIG_GREY_ONLY
  873.  
  874.         else:
  875.             return AGENT_CONFIG_INVALID
  876.  
  877.     else:
  878.         if AGENT_TYPE_BLACK in pens and AGENT_TYPE_CMY in pens:
  879.             return AGENT_CONFIG_COLOR_AND_BLACK
  880.  
  881.         elif AGENT_TYPE_CMY in pens and AGENT_TYPE_KCM in pens:
  882.             return AGENT_CONFIG_COLOR_AND_PHOTO
  883.  
  884.         elif AGENT_TYPE_CMY in pens and AGENT_TYPE_GGK in pens:
  885.             return AGENT_CONFIG_COLOR_AND_GREY
  886.  
  887.         else:
  888.             return AGENT_CONFIG_INVALID
  889.  
  890.  
  891. def getFaxStatus(dev):
  892.     tx_active, rx_active = False, False
  893.  
  894.     if dev.io_mode not in (IO_MODE_UNI, IO_MODE_RAW):
  895.         try:
  896.             dev.openPML()
  897.  
  898.             result_code, tx_state = dev.getPML(pml.OID_FAXJOB_TX_STATUS)
  899.  
  900.             if result_code == ERROR_SUCCESS and tx_state:
  901.                 if tx_state not in (pml.FAXJOB_TX_STATUS_IDLE, pml.FAXJOB_TX_STATUS_DONE):
  902.                     tx_active = True
  903.  
  904.             result_code, rx_state = dev.getPML(pml.OID_FAXJOB_RX_STATUS)
  905.  
  906.             if result_code == ERROR_SUCCESS and rx_state:
  907.                 if rx_state not in (pml.FAXJOB_RX_STATUS_IDLE, pml.FAXJOB_RX_STATUS_DONE):
  908.                     rx_active = True
  909.  
  910.         finally:
  911.             dev.closePML()
  912.  
  913.     return tx_active, rx_active
  914.  
  915.  
  916.  
  917.  
  918. TYPE6_STATUS_CODE_MAP = {
  919.      0    : STATUS_PRINTER_IDLE, #</DevStatusUnknown>
  920.     -19928: STATUS_PRINTER_IDLE,
  921.     -18995: STATUS_PRINTER_CANCELING,
  922.     -17974: STATUS_PRINTER_WARMING_UP,
  923.     -17973: STATUS_PRINTER_PEN_CLEANING, # sic
  924.     -18993: STATUS_PRINTER_BUSY,
  925.     -17949: STATUS_PRINTER_BUSY,
  926.     -19720: STATUS_PRINTER_MANUAL_DUPLEX_BLOCK,
  927.     -19678: STATUS_PRINTER_BUSY,
  928.     -19695: STATUS_PRINTER_OUT_OF_PAPER,
  929.     -17985: STATUS_PRINTER_MEDIA_JAM,
  930.     -19731: STATUS_PRINTER_OUT_OF_PAPER,
  931.     -18974: STATUS_PRINTER_BUSY, #?
  932.     -19730: STATUS_PRINTER_OUT_OF_PAPER,
  933.     -19729: STATUS_PRINTER_OUT_OF_PAPER,
  934.     -19933: STATUS_PRINTER_HARD_ERROR, # out of memory
  935.     -17984: STATUS_PRINTER_DOOR_OPEN,
  936.     -19694: STATUS_PRINTER_DOOR_OPEN,
  937.     -18992: STATUS_PRINTER_MANUAL_FEED_BLOCKED, # ?
  938.     -19690: STATUS_PRINTER_MEDIA_JAM, # tray 1
  939.     -19689: STATUS_PRINTER_MEDIA_JAM, # tray 2
  940.     -19611: STATUS_PRINTER_MEDIA_JAM, # tray 3
  941.     -19686: STATUS_PRINTER_MEDIA_JAM,
  942.     -19688: STATUS_PRINTER_MEDIA_JAM, # paper path
  943.     -19685: STATUS_PRINTER_MEDIA_JAM, # cart area
  944.     -19684: STATUS_PRINTER_MEDIA_JAM, # output bin
  945.     -18848: STATUS_PRINTER_MEDIA_JAM, # duplexer
  946.     -18847: STATUS_PRINTER_MEDIA_JAM, # door open
  947.     -18846: STATUS_PRINTER_MEDIA_JAM, # tray 2
  948.     -19687: STATUS_PRINTER_MEDIA_JAM, # open door
  949.     -17992: STATUS_PRINTER_MEDIA_JAM, # mispick
  950.     -19700: STATUS_PRINTER_HARD_ERROR, # invalid driver
  951.     -17996: STATUS_PRINTER_FUSER_ERROR, # fuser error
  952.     -17983: STATUS_PRINTER_FUSER_ERROR,
  953.     -17982: STATUS_PRINTER_FUSER_ERROR,
  954.     -17981: STATUS_PRINTER_FUSER_ERROR,
  955.     -17971: STATUS_PRINTER_FUSER_ERROR,
  956.     -17995: STATUS_PRINTER_HARD_ERROR, # beam error
  957.     -17994: STATUS_PRINTER_HARD_ERROR, # scanner error
  958.     -17993: STATUS_PRINTER_HARD_ERROR, # fan error
  959.     -18994: STATUS_PRINTER_HARD_ERROR,
  960.     -17986: STATUS_PRINTER_HARD_ERROR,
  961.     -19904: STATUS_PRINTER_HARD_ERROR,
  962.     -19701: STATUS_PRINTER_NON_HP_INK, # [sic]
  963.     -19613: STATUS_PRINTER_IDLE, # HP
  964.     -19654: STATUS_PRINTER_NON_HP_INK, # [sic]
  965.     -19682: STATUS_PRINTER_HARD_ERROR, # resinstall
  966.     -19693: STATUS_PRINTER_IDLE, # ?? To Accept
  967.     -19752: STATUS_PRINTER_LOW_TONER,
  968.     -19723: STATUS_PRINTER_BUSY,
  969.     -19703: STATUS_PRINTER_BUSY,
  970.     -19739: STATUS_PRINTER_NO_TONER,
  971.     -19927: STATUS_PRINTER_BUSY,
  972.     -19932: STATUS_PRINTER_BUSY,
  973.     -19931: STATUS_PRINTER_BUSY,
  974.     -11989: STATUS_PRINTER_BUSY,
  975.     -11995: STATUS_PRINTER_BUSY, # ADF loaded
  976.     -19954: STATUS_PRINTER_CANCELING,
  977.     -19955: STATUS_PRINTER_REPORT_PRINTING,
  978.     -19956: STATUS_PRINTER_REPORT_PRINTING,
  979.     -19934: STATUS_PRINTER_HARD_ERROR,
  980.     -19930: STATUS_PRINTER_BUSY,
  981.     -11990: STATUS_PRINTER_DOOR_OPEN,
  982.     -11999: STATUS_PRINTER_MEDIA_JAM, # ADF
  983.     -12000: STATUS_PRINTER_MEDIA_JAM, # ADF
  984.     -11998: STATUS_PRINTER_MEDIA_JAM, # ADF
  985.     -11986: STATUS_PRINTER_HARD_ERROR, # scanner
  986.     -11994: STATUS_PRINTER_BUSY,
  987.     -14967: STATUS_PRINTER_BUSY,
  988.     -19912: STATUS_PRINTER_HARD_ERROR,
  989.     -14962: STATUS_PRINTER_BUSY, # copy pending
  990.     -14971: STATUS_PRINTER_BUSY, # copying
  991.     -14973: STATUS_PRINTER_BUSY, # copying being canceled
  992.     -14972: STATUS_PRINTER_BUSY, # copying canceled
  993.     -14966: STATUS_PRINTER_DOOR_OPEN,
  994.     -14974: STATUS_PRINTER_MEDIA_JAM,
  995.     -14969: STATUS_PRINTER_HARD_ERROR,
  996.     -14968: STATUS_PRINTER_HARD_ERROR,
  997.     -12996: STATUS_PRINTER_BUSY, # scan
  998.     -12994: STATUS_PRINTER_BUSY, # scan
  999.     -12993: STATUS_PRINTER_BUSY, # scan
  1000.     -12991: STATUS_PRINTER_BUSY, # scan
  1001.     -12995: STATUS_PRINTER_BUSY, # scan
  1002.     -12997: STATUS_PRINTER_HARD_ERROR, # scan
  1003.     -12990: STATUS_PRINTER_BUSY,
  1004.     -12998: STATUS_PRINTER_BUSY,
  1005.     -13000: STATUS_PRINTER_DOOR_OPEN,
  1006.     -12999: STATUS_PRINTER_MEDIA_JAM,
  1007.     -13859: STATUS_PRINTER_BUSY,
  1008.     -13858: STATUS_PRINTER_BUSY, #</DevStatusDialingOut>
  1009.     -13868: STATUS_PRINTER_BUSY, #</DevStatusRedialPending>
  1010.     -13867: STATUS_PRINTER_BUSY, #</DevStatusFaxSendCanceled>
  1011.     -13857: STATUS_PRINTER_BUSY, #</DevStatusConnecting>
  1012.     -13856: STATUS_PRINTER_BUSY, #</DevStatusSendingPage>
  1013.     -13855: STATUS_PRINTER_BUSY, #</DevStatusOnePageSend>
  1014.     -13854: STATUS_PRINTER_BUSY, #</DevStatusMultiplePagesSent>
  1015.     -13853: STATUS_PRINTER_BUSY, #</DevStatusSenderCancelingFax>
  1016.     -13839: STATUS_PRINTER_BUSY, #</DevStatusIncomingCall>
  1017.     -13842: STATUS_PRINTER_BUSY, #</DevStatusBlockingFax>
  1018.     -13838: STATUS_PRINTER_BUSY, #</DevStatusReceivingFax>
  1019.     -13847: STATUS_PRINTER_BUSY, #</DevStatusSinglePageReceived>
  1020.     -13846: STATUS_PRINTER_BUSY, #</DevStatusDoublePagesReceived>
  1021.     -13845: STATUS_PRINTER_BUSY, #</DevStatusTriplePagesReceived>
  1022.     -13844: STATUS_PRINTER_BUSY, #</DevStatusPrintingFax>
  1023.     -13840: STATUS_PRINTER_BUSY, #</DevStatusCancelingFaxPrint>
  1024.     -13843: STATUS_PRINTER_BUSY, #</DevStatusFaxCancelingReceive>
  1025.     -13850: STATUS_PRINTER_BUSY, #</DevStatusFaxCanceledReceive>
  1026.     -13851: STATUS_PRINTER_BUSY, #</DevStatusFaxDelayedSendMemoryFull>
  1027.     -13836: STATUS_PRINTER_BUSY, #</DevStatusNoDialTone>
  1028.     -13864: STATUS_PRINTER_BUSY, #</DevStatusNoFaxAnswer>
  1029.     -13863: STATUS_PRINTER_BUSY, #</DevStatusFaxBusy>
  1030.     -13865: STATUS_PRINTER_BUSY, #</DevStatusNoDocumentSent>
  1031.     -13862: STATUS_PRINTER_BUSY, #</DevStatusFaxSendError>
  1032.     -13837: STATUS_PRINTER_BUSY, #</DevStatusT30Error>
  1033.     -13861: STATUS_PRINTER_BUSY, #</DevStatusFaxMemoryFullSend>
  1034.     -13866: STATUS_PRINTER_BUSY, #</DevStatusADFNotCleared>
  1035.     -13841: STATUS_PRINTER_BUSY, #</DevStatusNoFaxDetected>
  1036.     -13848: STATUS_PRINTER_BUSY, #</DevStatusFaxMemoryFullReceive>
  1037.     -13849: STATUS_PRINTER_BUSY, #</DevStatusFaxReceiveError>
  1038.  
  1039. }
  1040.  
  1041. def StatusType6(dev): #  LaserJet Status (XML)
  1042.     info_device_status = cStringIO.StringIO()
  1043.     info_ssp = cStringIO.StringIO()
  1044.  
  1045.     try:
  1046.         dev.getEWSUrl("/hp/device/info_device_status.xml", info_device_status)
  1047.         dev.getEWSUrl("/hp/device/info_ssp.xml", info_ssp)
  1048.     except:
  1049.         pass
  1050.  
  1051.     info_device_status = info_device_status.getvalue()
  1052.     info_ssp = info_ssp.getvalue()
  1053.  
  1054.     device_status = {}
  1055.     ssp = {}
  1056.  
  1057.     if info_device_status:
  1058.         try:
  1059.             log.debug_block("info_device_status", info_device_status)
  1060.             device_status = utils.XMLToDictParser().parseXML(info_device_status)
  1061.             log.debug(device_status)
  1062.         except expat.ExpatError:
  1063.             log.error("Device Status XML parse error")
  1064.             device_status = {}
  1065.  
  1066.     if info_ssp:
  1067.         try:
  1068.             log.debug_block("info_spp", info_ssp)
  1069.             ssp = utils.XMLToDictParser().parseXML(info_ssp)
  1070.             log.debug(ssp)
  1071.         except expat.ExpatError:
  1072.             log.error("SSP XML parse error")
  1073.             ssp = {}
  1074.  
  1075.     status_code = device_status.get('devicestatuspage-devicestatus-statuslist-status-code-0', 0)
  1076.  
  1077.     if not status_code:
  1078.         status_code = ssp.get('devicestatuspage-devicestatus-statuslist-status-code-0', 0)
  1079.  
  1080.     black_supply_level = device_status.get('devicestatuspage-suppliesstatus-blacksupply-percentremaining', 0)
  1081.     black_supply_low = ssp.get('suppliesstatuspage-blacksupply-lowreached', 0)
  1082.     agents = []
  1083.  
  1084.     agents.append({  'kind' : AGENT_KIND_TONER_CARTRIDGE,
  1085.                      'type' : AGENT_TYPE_BLACK,
  1086.                      'health' : 0,
  1087.                      'level' : black_supply_level,
  1088.                      'level-trigger' : 0,
  1089.                   })
  1090.  
  1091.     if dev.tech_type == TECH_TYPE_COLOR_LASER:
  1092.         cyan_supply_level = device_status.get('devicestatuspage-suppliesstatus-cyansupply-percentremaining', 0)
  1093.         agents.append({  'kind' : AGENT_KIND_TONER_CARTRIDGE,
  1094.                          'type' : AGENT_TYPE_CYAN,
  1095.                          'health' : 0,
  1096.                          'level' : cyan_supply_level,
  1097.                          'level-trigger' : 0,
  1098.                       })
  1099.  
  1100.         magenta_supply_level = device_status.get('devicestatuspage-suppliesstatus-magentasupply-percentremaining', 0)
  1101.         agents.append({  'kind' : AGENT_KIND_TONER_CARTRIDGE,
  1102.                          'type' : AGENT_TYPE_MAGENTA,
  1103.                          'health' : 0,
  1104.                          'level' : magenta_supply_level,
  1105.                          'level-trigger' : 0,
  1106.                       })
  1107.  
  1108.         yellow_supply_level = device_status.get('devicestatuspage-suppliesstatus-yellowsupply-percentremaining', 0)
  1109.         agents.append({  'kind' : AGENT_KIND_TONER_CARTRIDGE,
  1110.                          'type' : AGENT_TYPE_YELLOW,
  1111.                          'health' : 0,
  1112.                          'level' : yellow_supply_level,
  1113.                          'level-trigger' : 0,
  1114.                       })
  1115.  
  1116.     return {'revision' :    STATUS_REV_UNKNOWN,
  1117.              'agents' :      agents,
  1118.              'top-door' :    0,
  1119.              'supply-door' : 0,
  1120.              'duplexer' :    1,
  1121.              'photo-tray' :  0,
  1122.              'in-tray1' :    1,
  1123.              'in-tray2' :    1,
  1124.              'media-path' :  1,
  1125.              'status-code' : TYPE6_STATUS_CODE_MAP.get(status_code, STATUS_PRINTER_IDLE),
  1126.            }
  1127.  
  1128. # PJL status codes
  1129. PJL_STATUS_MAP = {
  1130.     10001: STATUS_PRINTER_IDLE, # online
  1131.     10002: STATUS_PRINTER_OFFLINE, # offline
  1132.     10003: STATUS_PRINTER_WARMING_UP,
  1133.     10004: STATUS_PRINTER_BUSY, # self test
  1134.     10005: STATUS_PRINTER_BUSY, # reset
  1135.     10006: STATUS_PRINTER_LOW_TONER,
  1136.     10007: STATUS_PRINTER_CANCELING,
  1137.     10010: STATUS_PRINTER_SERVICE_REQUEST,
  1138.     10011: STATUS_PRINTER_OFFLINE,
  1139.     10013: STATUS_PRINTER_BUSY,
  1140.     10014: STATUS_PRINTER_REPORT_PRINTING,
  1141.     10015: STATUS_PRINTER_BUSY,
  1142.     10016: STATUS_PRINTER_BUSY,
  1143.     10017: STATUS_PRINTER_REPORT_PRINTING,
  1144.     10018: STATUS_PRINTER_BUSY,
  1145.     10019: STATUS_PRINTER_BUSY,
  1146.     10020: STATUS_PRINTER_BUSY,
  1147.     10021: STATUS_PRINTER_BUSY,
  1148.     10022: STATUS_PRINTER_REPORT_PRINTING,
  1149.     10023: STATUS_PRINTER_PRINTING,
  1150.     10024: STATUS_PRINTER_SERVICE_REQUEST,
  1151.     10025: STATUS_PRINTER_SERVICE_REQUEST,
  1152.     10026: STATUS_PRINTER_BUSY,
  1153.     10027: STATUS_PRINTER_MEDIA_JAM,
  1154.     10028: STATUS_PRINTER_REPORT_PRINTING,
  1155.     10029: STATUS_PRINTER_PRINTING,
  1156.     10030: STATUS_PRINTER_BUSY,
  1157.     10031: STATUS_PRINTER_BUSY,
  1158.     10032: STATUS_PRINTER_BUSY,
  1159.     10033: STATUS_PRINTER_SERVICE_REQUEST,
  1160.     10034: STATUS_PRINTER_CANCELING,
  1161.     10035: STATUS_PRINTER_PRINTING,
  1162.     10036: STATUS_PRINTER_WARMING_UP,
  1163.     10200: STATUS_PRINTER_LOW_BLACK_TONER,
  1164.     10201: STATUS_PRINTER_LOW_CYAN_TONER,
  1165.     10202: STATUS_PRINTER_LOW_MAGENTA_TONER,
  1166.     10203: STATUS_PRINTER_LOW_YELLOW_TONER,
  1167.     10204: STATUS_PRINTER_LOW_TONER, # order image drum
  1168.     10205: STATUS_PRINTER_LOW_BLACK_TONER, # order black drum
  1169.     10206: STATUS_PRINTER_LOW_CYAN_TONER, # order cyan drum
  1170.     10207: STATUS_PRINTER_LOW_MAGENTA_TONER, # order magenta drum
  1171.     10208: STATUS_PRINTER_LOW_YELLOW_TONER, # order yellow drum
  1172.     10209: STATUS_PRINTER_LOW_BLACK_TONER,
  1173.     10210: STATUS_PRINTER_LOW_CYAN_TONER,
  1174.     10211: STATUS_PRINTER_LOW_MAGENTA_TONER,
  1175.     10212: STATUS_PRINTER_LOW_YELLOW_TONER,
  1176.     10213: STATUS_PRINTER_SERVICE_REQUEST, # order transport kit
  1177.     10214: STATUS_PRINTER_SERVICE_REQUEST, # order cleaning kit
  1178.     10215: STATUS_PRINTER_SERVICE_REQUEST, # order transfer kit
  1179.     10216: STATUS_PRINTER_SERVICE_REQUEST, # order fuser kit
  1180.     10217: STATUS_PRINTER_SERVICE_REQUEST, # maintenance
  1181.     10218: STATUS_PRINTER_LOW_TONER,
  1182.     10300: STATUS_PRINTER_LOW_BLACK_TONER, # replace black toner
  1183.     10301: STATUS_PRINTER_LOW_CYAN_TONER, # replace cyan toner
  1184.     10302: STATUS_PRINTER_LOW_MAGENTA_TONER, # replace magenta toner
  1185.     10303: STATUS_PRINTER_LOW_YELLOW_TONER, # replace yellow toner
  1186.     10304: STATUS_PRINTER_SERVICE_REQUEST, # replace image drum
  1187.     10305: STATUS_PRINTER_SERVICE_REQUEST, # replace black drum
  1188.     10306: STATUS_PRINTER_SERVICE_REQUEST, # replace cyan drum
  1189.     10307: STATUS_PRINTER_SERVICE_REQUEST, # replace magenta drum
  1190.     10308: STATUS_PRINTER_SERVICE_REQUEST, # replace yellow drum
  1191.     10309: STATUS_PRINTER_SERVICE_REQUEST, # replace black cart
  1192.     10310: STATUS_PRINTER_SERVICE_REQUEST, # replace cyan cart
  1193.     10311: STATUS_PRINTER_SERVICE_REQUEST, # replace magenta cart
  1194.     10312: STATUS_PRINTER_SERVICE_REQUEST, # replace yellow cart
  1195.     10313: STATUS_PRINTER_SERVICE_REQUEST, # replace transport kit
  1196.     10314: STATUS_PRINTER_SERVICE_REQUEST, # replace cleaning kit
  1197.     10315: STATUS_PRINTER_SERVICE_REQUEST, # replace transfer kit
  1198.     10316: STATUS_PRINTER_SERVICE_REQUEST, # replace fuser kit
  1199.     10317: STATUS_PRINTER_SERVICE_REQUEST,
  1200.     10318: STATUS_PRINTER_SERVICE_REQUEST, # replace supplies
  1201.     10400: STATUS_PRINTER_NON_HP_INK, # [sic]
  1202.     10401: STATUS_PRINTER_IDLE,
  1203.     10402: STATUS_PRINTER_SERVICE_REQUEST,
  1204.     10403: STATUS_PRINTER_IDLE,
  1205.     # 11xyy - Background paper-loading
  1206.     # 12xyy - Background paper-tray status
  1207.     # 15xxy - Output-bin status
  1208.     # 20xxx - PJL parser errors
  1209.     # 25xxx - PJL parser warnings
  1210.     # 27xxx - PJL semantic errors
  1211.     # 30xxx - Auto continuable conditions
  1212.     30119: STATUS_PRINTER_MEDIA_JAM,
  1213.     # 32xxx - PJL file system errors
  1214.     # 35xxx - Potential operator intervention conditions
  1215.     # 40xxx - Operator intervention conditions
  1216.     40021: STATUS_PRINTER_DOOR_OPEN,
  1217.     40022: STATUS_PRINTER_MEDIA_JAM,
  1218.     40038: STATUS_PRINTER_LOW_TONER,
  1219.     40600: STATUS_PRINTER_NO_TONER,
  1220.     # 41xyy - Foreground paper-loading messages
  1221.     # 43xyy - Optional paper handling device messages
  1222.     # 44xyy - LJ 4xxx/5xxx paper jam messages
  1223.     # 50xxx - Hardware errors
  1224.     # 55xxx - Personality errors
  1225.  
  1226. }
  1227.  
  1228. MIN_PJL_ERROR_CODE = 10001
  1229. DEFAULT_PJL_ERROR_CODE = 10001
  1230.  
  1231. def MapPJLErrorCode(error_code, str_code=None):
  1232.     if error_code < MIN_PJL_ERROR_CODE:
  1233.         return STATUS_PRINTER_BUSY
  1234.  
  1235.     if str_code is None:
  1236.         str_code = str(error_code)
  1237.  
  1238.     if len(str_code) < 5:
  1239.         return STATUS_PRINTER_BUSY
  1240.  
  1241.     status_code = PJL_STATUS_MAP.get(error_code, None)
  1242.  
  1243.     if status_code is None:
  1244.         status_code = STATUS_PRINTER_BUSY
  1245.  
  1246.         if 10999 < error_code < 12000: # 11xyy - Background paper-loading
  1247.             # x = tray #
  1248.             # yy = media code
  1249.             tray = int(str_code[2])
  1250.             media = int(str_code[3:])
  1251.             log.debug("Background paper loading for tray #%d" % tray)
  1252.             log.debug("Media code = %d" % media)
  1253.  
  1254.         elif 11999 < error_code < 13000: # 12xyy - Background paper-tray status
  1255.             # x = tray #
  1256.             # yy = status code
  1257.             tray = int(str_code[2])
  1258.             status = int(str_code[3:])
  1259.             log.debug("Background paper tray status for tray #%d" % tray)
  1260.             log.debug("Status code = %d" % status)
  1261.  
  1262.         elif 14999 < error_code < 16000: # 15xxy - Output-bin status
  1263.             # xx = output bin
  1264.             # y = status code
  1265.             bin = int(str_code[2:4])
  1266.             status = int(str_code[4])
  1267.             log.debug("Output bin full for bin #%d" % bin)
  1268.             status_code = STATUS_PRINTER_OUTPUT_BIN_FULL
  1269.  
  1270.         elif 19999 < error_code < 28000: # 20xxx, 25xxx, 27xxx PJL errors
  1271.             status_code = STATUS_PRINTER_SERVICE_REQUEST
  1272.  
  1273.         elif 29999 < error_code < 31000: # 30xxx - Auto continuable conditions
  1274.             log.debug("Auto continuation condition #%d" % error_code)
  1275.             status_code = STATUS_PRINTER_BUSY
  1276.  
  1277.         elif 34999 < error_code < 36000: # 35xxx - Potential operator intervention conditions
  1278.             status_code = STATUS_PRINTER_SERVICE_REQUEST
  1279.  
  1280.         elif 39999 < error_code < 41000: # 40xxx - Operator intervention conditions
  1281.             status_code = STATUS_PRINTER_SERVICE_REQUEST
  1282.  
  1283.         elif 40999 < error_code < 42000: # 41xyy - Foreground paper-loading messages
  1284.             # x = tray
  1285.             # yy = media code
  1286.             tray = int(str_code[2])
  1287.             media = int(str_code[3:])
  1288.             log.debug("Foreground paper loading for tray #%d" % tray)
  1289.             log.debug("Media code = %d" % media)
  1290.             status_code = STATUS_PRINTER_OUT_OF_PAPER
  1291.  
  1292.         elif 41999 < error_code < 43000:
  1293.             status_code = STATUS_PRINTER_MEDIA_JAM
  1294.  
  1295.         elif 42999 < error_code < 44000: # 43xyy - Optional paper handling device messages
  1296.             status_code = STATUS_PRINTER_SERVICE_REQUEST
  1297.  
  1298.         elif 43999 < error_code < 45000: # 44xyy - LJ 4xxx/5xxx paper jam messages
  1299.             status_code = STATUS_PRINTER_MEDIA_JAM
  1300.  
  1301.         elif 49999 < error_code < 51000: # 50xxx - Hardware errors
  1302.             status_code = STATUS_PRINTER_HARD_ERROR
  1303.  
  1304.         elif 54999 < error_code < 56000 : # 55xxx - Personality errors
  1305.             status_code = STATUS_PRINTER_HARD_ERROR
  1306.  
  1307.     log.debug("Mapped PJL error code %d to status code %d" % (error_code, status_code))
  1308.     return status_code
  1309.  
  1310.  
  1311. pjl_code_pat = re.compile("""^CODE\s*=\s*(\d.*)$""", re.IGNORECASE)
  1312.  
  1313.  
  1314.  
  1315. def StatusType8(dev): #  LaserJet PJL (B&W only)
  1316.     try:
  1317.         # Will error if printer is busy printing...
  1318.         dev.openPrint()
  1319.     except Error, e:
  1320.         log.warn(e.msg)
  1321.         status_code = STATUS_PRINTER_BUSY
  1322.     else:
  1323.         try:
  1324.             try:
  1325.                 dev.writePrint("\x1b%-12345X@PJL INFO STATUS \r\n\x1b%-12345X")
  1326.                 pjl_return = dev.readPrint(1024, timeout=5, allow_short_read=True)
  1327.                 dev.close()
  1328.  
  1329.                 log.debug_block("PJL return:", pjl_return)
  1330.  
  1331.                 str_code = '10001'
  1332.  
  1333.                 for line in pjl_return.splitlines():
  1334.                     line = line.strip()
  1335.                     match = pjl_code_pat.match(line)
  1336.  
  1337.                     if match is not None:
  1338.                         str_code = match.group(1)
  1339.                         break
  1340.  
  1341.                 log.debug("Code = %s" % str_code)
  1342.  
  1343.                 try:
  1344.                     error_code = int(str_code)
  1345.                 except ValueError:
  1346.                     error_code = DEFAULT_PJL_ERROR_CODE
  1347.  
  1348.                 log.debug("Error code = %d" % error_code)
  1349.  
  1350.                 status_code = MapPJLErrorCode(error_code, str_code)
  1351.             except Error:
  1352.                 status_code = STATUS_PRINTER_HARD_ERROR
  1353.         finally:
  1354.             try:
  1355.                 dev.closePrint()
  1356.             except Error:
  1357.                 pass
  1358.  
  1359.     agents = []
  1360.  
  1361.     # TODO: Only handles mono lasers...
  1362.     if status_code in (STATUS_PRINTER_LOW_TONER, STATUS_PRINTER_LOW_BLACK_TONER):
  1363.         health = AGENT_HEALTH_OK
  1364.         level_trigger = AGENT_LEVEL_TRIGGER_MAY_BE_LOW
  1365.         level = 0
  1366.  
  1367.     elif status_code == STATUS_PRINTER_NO_TONER:
  1368.         health = AGENT_HEALTH_MISINSTALLED
  1369.         level_trigger = AGENT_LEVEL_TRIGGER_MAY_BE_LOW
  1370.         level = 0
  1371.  
  1372.     else:
  1373.         health = AGENT_HEALTH_OK
  1374.         level_trigger = AGENT_LEVEL_TRIGGER_SUFFICIENT_0
  1375.         level = 100
  1376.  
  1377.     log.debug("Agent: health=%d, level=%d, trigger=%d" % (health, level, level_trigger))
  1378.  
  1379.     agents.append({  'kind' : AGENT_KIND_TONER_CARTRIDGE,
  1380.                      'type' : AGENT_TYPE_BLACK,
  1381.                      'health' : health,
  1382.                      'level' : level,
  1383.                      'level-trigger' : level_trigger,
  1384.                   })
  1385.  
  1386.     if dev.tech_type == TECH_TYPE_COLOR_LASER:
  1387.         level = 100
  1388.         level_trigger = AGENT_LEVEL_TRIGGER_SUFFICIENT_0
  1389.         if status_code == STATUS_PRINTER_LOW_CYAN_TONER:
  1390.             level = 0
  1391.             level_trigger = AGENT_LEVEL_TRIGGER_MAY_BE_LOW
  1392.  
  1393.         log.debug("Agent: health=%d, level=%d, trigger=%d" % (health, level, level_trigger))
  1394.  
  1395.         agents.append({  'kind' : AGENT_KIND_TONER_CARTRIDGE,
  1396.                          'type' : AGENT_TYPE_CYAN,
  1397.                          'health' : AGENT_HEALTH_OK,
  1398.                          'level' : level,
  1399.                          'level-trigger' : level_trigger,
  1400.                       })
  1401.  
  1402.         level = 100
  1403.         level_trigger = AGENT_LEVEL_TRIGGER_SUFFICIENT_0
  1404.         if status_code == STATUS_PRINTER_LOW_MAGENTA_TONER:
  1405.             level = 0
  1406.             level_trigger = AGENT_LEVEL_TRIGGER_MAY_BE_LOW
  1407.  
  1408.         log.debug("Agent: health=%d, level=%d, trigger=%d" % (health, level, level_trigger))
  1409.  
  1410.         agents.append({  'kind' : AGENT_KIND_TONER_CARTRIDGE,
  1411.                          'type' : AGENT_TYPE_MAGENTA,
  1412.                          'health' : AGENT_HEALTH_OK,
  1413.                          'level' : level,
  1414.                          'level-trigger' : level_trigger,
  1415.                       })
  1416.  
  1417.         level = 100
  1418.         level_trigger = AGENT_LEVEL_TRIGGER_SUFFICIENT_0
  1419.         if status_code == STATUS_PRINTER_LOW_YELLOW_TONER:
  1420.             level = 0
  1421.             level_trigger = AGENT_LEVEL_TRIGGER_MAY_BE_LOW
  1422.  
  1423.         log.debug("Agent: health=%d, level=%d, trigger=%d" % (health, level, level_trigger))
  1424.  
  1425.         agents.append({  'kind' : AGENT_KIND_TONER_CARTRIDGE,
  1426.                          'type' : AGENT_TYPE_YELLOW,
  1427.                          'health' : AGENT_HEALTH_OK,
  1428.                          'level' : level,
  1429.                          'level-trigger' : level_trigger,
  1430.                       })
  1431.  
  1432.     if status_code == 40021:
  1433.         top_door = 0
  1434.     else:
  1435.         top_door = 1
  1436.  
  1437.     log.debug("Status code = %d" % status_code)
  1438.  
  1439.     return { 'revision' :    STATUS_REV_UNKNOWN,
  1440.              'agents' :      agents,
  1441.              'top-door' :    top_door,
  1442.              'supply-door' : top_door,
  1443.              'duplexer' :    0,
  1444.              'photo-tray' :  0,
  1445.              'in-tray1' :    1,
  1446.              'in-tray2' :    1,
  1447.              'media-path' :  1,
  1448.              'status-code' : status_code,
  1449.            }
  1450.  
  1451.  
  1452.  
  1453.  
  1454.